home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / win / c / winet.com / SEGMENTS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-08  |  7.2 KB  |  283 lines

  1. /*
  2.  * This file contains procedures connected with maintaining a list of
  3.  * segments in use in the program.
  4.  * 
  5.  * The following operations are defined:
  6.  *     LOOKUP MODULE
  7.  *           Returns head of segment list for named module.
  8.  *           For new module it inserts a new module name if there is room, otherwise the
  9.  *           result will be NULL.
  10.  *     DEFINE SEGMENT
  11.  *           Look up module name. If o.k. search for segment by number. If not found
  12.  *           attempt to insert a new segment into list. Store segment location and enter segment
  13.  *           into hash table.
  14.  *     MOVE SEGMENT
  15.  *           Look for segment in hash table. Remove old hash table entry, change position,
  16.  *           re-enter position in hash table.
  17.  *     DISCARD SEGMENT
  18.  *           Remove segment from hash table. Set location to 0.
  19.  *     FIND SEGMENT
  20.  *           Lookup segment in hash table. Returns pointer to entry.
  21.  */
  22. #include <stdio.h>
  23. #include <process.h>
  24. #include <malloc.h>
  25. #include <dgb.h>
  26. #include <exc.h>
  27. #include "types.h"
  28. #include "profile.h"
  29. #include "segments.h"
  30. #include "trace.h"
  31. #include "symfile.h"
  32.  
  33. #define NextHash(i)    ((i) = ((i)+1)%MAXHASHVAL)
  34. PSEGMENT hashtable[MAXHASHVAL] = { UNUSED };
  35. MODULENAME modules[MAXMODULE];
  36. SEGMENT segs[MAXSEGMENT];
  37. PSEGMENT FreeSeg = &segs[0];
  38. PMODULE FreeMod = &modules[0];
  39.  
  40. /* This procedure has to return a success code because I don't trust
  41.  * the exception handling to work proerly when I'm in an interrupt
  42.  * routine (SS != DS).
  43.  */
  44. PMODULE LookupModule (m)
  45. LPSTR m;
  46. {
  47.    PMODULE pm;
  48.    LPSTR s, t;
  49.    for (pm = &modules[0]; pm < FreeMod; pm++)
  50.    {
  51.       for (s = m, t = pm->name; *s == *t; s++, t++)
  52.       {
  53.      if (*t == 0) return pm;
  54.       }
  55.    }
  56.    if (FreeMod < ARRAY_END(modules))
  57.    {
  58.       WORD i;
  59.       s = m;
  60.       for (i = 0; i <= 8; i++)
  61.       {
  62.      FreeMod->name[i] = *s++;
  63.       }
  64.       FreeMod->name[8] = 0;
  65.       FreeMod->pseg = NULL;
  66.       return FreeMod++;
  67.    }
  68.    return NULL;
  69. }
  70.  
  71. PSEGMENT DefineSegment (ModName, Ordinal, SegLoc, Instance, Type)
  72. LPSTR ModName;
  73. WORD Ordinal, SegLoc, Instance, Type;
  74. {
  75.    PSEGMENT ps = FindSegment (ModName, Ordinal, Instance, Type);
  76.    if (ps == NULL) return NULL;
  77.    HashRemove (ps);
  78.    ps->location = SegLoc;
  79.    HashInsert (ps);
  80.    return ps;
  81. }
  82.  
  83. void MoveSegment (from, to)
  84. WORD from, to;
  85. {
  86.    PSEGMENT ps = HashFind (from);
  87.    unless (ps == NULL)
  88.    {
  89.       HashRemove (ps);
  90.       ps->location = to;
  91.       unless (to == NULL) HashInsert(ps);
  92.       /*trace("Moved %s@%d from %w to %w\n", (LPSTR) ps->module->name, ps->ordinal, from, to);*/
  93.    }
  94. }
  95.  
  96. void DiscardSegment (loc)
  97. WORD loc;
  98. {
  99.    PSEGMENT ps = HashFind (loc);
  100.    unless (ps == NULL)
  101.    {
  102.       HashRemove (ps);
  103.       ps->location = 0;
  104.       /*trace("Discard %s@%d\n", (LPSTR) ps->module->name, ps->ordinal);*/
  105.    }
  106. }
  107.  
  108. PSEGMENT FindSegment (ModName, Ordinal, Instance, Type)
  109. LPSTR ModName;
  110. WORD Ordinal, Instance;
  111. WORD Type;
  112. {
  113.    PMODULE pm = LookupModule (ModName);
  114.    PSEGMENT *pps;
  115.    if (pm == NULL) return NULL;
  116.    pps = &pm->pseg;
  117.    while (*pps != NULL)
  118.    {
  119.       if ((*pps)->ordinal == Ordinal && (*pps)->instance == Instance)
  120.       {
  121.      /*trace("Found segment %s\n", (LPSTR) ModName);*/
  122.      return *pps;
  123.       }
  124.       pps = &(*pps)->next;
  125.    }
  126.    if (FreeSeg < ARRAY_END(segs))
  127.    {
  128.       /*trace("New segment %s\n", (LPSTR) ModName);*/
  129.       *pps = FreeSeg;
  130.       FreeSeg->ordinal = Ordinal;
  131.       FreeSeg->instance = Instance;
  132.       FreeSeg->type = Type;
  133.       FreeSeg->module = pm;
  134.       FreeSeg->location = 0;
  135.       FreeSeg->Procs = NULL;
  136.       FreeSeg->hitcount = 0;
  137.       return FreeSeg++;
  138.    }
  139.    return NULL;
  140. }
  141.  
  142. void HashRemove (s)
  143. PSEGMENT s;
  144. {
  145.    WORD index = s->location % MAXHASHVAL;
  146.    WORD nxt;
  147.    if (s->location == 0) return;
  148.    until (hashtable[index] == s)
  149.    {
  150.       if (hashtable[index] == UNUSED) return; /* Not found */
  151.       NextHash (index);
  152.    }
  153.    hashtable[index] = DELETED;
  154.    if (hashtable[(index+1) % MAXHASHVAL] == UNUSED)
  155.    {
  156.       while (hashtable[index] == DELETED)
  157.       {
  158.      hashtable[index] = UNUSED;
  159.      index = (index+MAXHASHVAL-1) % MAXHASHVAL;
  160.       }
  161.    }
  162. }
  163.  
  164. void HashInsert (s)
  165. PSEGMENT s;
  166. {
  167.    WORD index = s->location % MAXHASHVAL;
  168.    if (s->location == 0) return;
  169.  
  170.    until (hashtable[index] == s || hashtable[index] == UNUSED || hashtable[index] == DELETED)
  171.    {
  172.       NextHash(index);
  173.    }
  174.    hashtable[index] = s;
  175. }
  176.  
  177. PSEGMENT HashFind (w)
  178. WORD w;
  179. {
  180.    WORD index = w % MAXHASHVAL;
  181.    until (hashtable[index] == UNUSED)
  182.    {
  183.       if (hashtable[index] != DELETED && hashtable[index]->location == w)
  184.       {
  185.      return hashtable[index];
  186.       }
  187.       NextHash(index);
  188.    }
  189.    return NULL;
  190. }
  191.  
  192. #define RATIO(x) { ratio = (unsigned long) (x) * 10000L / totalhits; rathi = (WORD) ratio/100; ratlo = (WORD) ratio%100; }
  193.  
  194. void PrintSegments()
  195. {
  196.    unsigned long ratio;
  197.    WORD rathi, ratlo;
  198.    PSEGMENT seg;
  199.    FILE *outf = stderr;
  200.    BOOL DoProcs = FALSE;
  201.    
  202.    if (OutputFileName != NULL)
  203.    {
  204.       outf = fopen(OutputFileName, "w");
  205.       if (outf == NULL)
  206.       {
  207.      BadFile = OutputFileName;
  208.      exc_raise (OP_FAILED);
  209.       }
  210.    }
  211.  
  212.    fprintf(outf, "Microsoft windows statistics\nSample interval %dms\nTotal hits %ld\n", TimerPeriod, totalhits);
  213.    fprintf(outf, "\nSegments\n");
  214.    for (seg = &segs[0]; seg < FreeSeg; seg++) if (seg->hitcount != 0)
  215.    {
  216.       WORD flag = seg->Procs != NULL && seg->hitcount != 0;
  217.       if (seg->Procs != 0) DoProcs = TRUE;
  218.       RATIO (seg->hitcount);
  219.       fprintf(outf, "%2u.%02u%% %5u ", rathi, ratlo, seg->hitcount);
  220.  
  221.       if (seg->Procs != 0)
  222.      fprintf(outf, "%s!%s\n", seg->module->name, seg->Procs->segname->s);
  223.       else if (seg->type > 1)
  224.      fprintf(outf, "%s@%04x\n", seg->module->name, seg->type);
  225.       else
  226.      fprintf(outf, "%s!%s:%u\n", seg->module->name, (seg->type == 0 ? "Code":"Data"), seg->ordinal+1);
  227.    }
  228.    if (otherhits != 0)
  229.    {
  230.       RATIO (otherhits);
  231.       fprintf(outf, "%2u.%02u%% %5u Others\n", rathi, ratlo, otherhits);
  232.    }
  233.  
  234.    if (DoProcs)
  235.    {
  236.       fprintf(outf, "\nProcedures\n");
  237.       for (seg = &segs[0]; seg < FreeSeg; seg++) if (seg->hitcount != 0 && seg->Procs != 0)
  238.       {
  239.      WORD i;
  240.      WORD n = seg->Procs->len;
  241.      for (i = 0; i < n; i++) if (seg->Procs->vals[i].count != 0)
  242.      {
  243.         PNSTR sym = FindSymbol (seg->Procs->filename, seg->ordinal+1, seg->Procs->vals[i].label);
  244.         if (sym == NULL)
  245.         {
  246.            BadFile = seg->Procs->filename;
  247.            exc_raise(BAD_SYMBOL);
  248.         }
  249.         else
  250.         {
  251.            RATIO(seg->Procs->vals[i].count);
  252.            fprintf(outf, "%2u.%02u%% %5u %s!%s:%s\n", rathi, ratlo,
  253.           seg->Procs->vals[i].count,
  254.              seg->module->name, seg->Procs->segname->s, sym->s);
  255.           free((char *) sym);
  256.         }
  257.      }
  258.       }
  259.    }
  260. }
  261.  
  262. /*
  263.  * This procedure allows the stats to be reset at run-time by a multiplex interrupt.
  264.  */
  265. void far ClearSegments()
  266. {
  267.    PSEGMENT seg;
  268.  
  269.    for (seg = &segs[0]; seg < FreeSeg; seg++) if (seg->hitcount != 0)
  270.    {
  271.       seg->hitcount = 0;
  272.       if (seg->Procs != NULL)
  273.       {
  274.      WORD i;
  275.      WORD n = seg->Procs->len;
  276.      for (i = 0; i < n; i++)
  277.         seg->Procs->vals[i].count = 0;
  278.      seg->Procs = NULL;
  279.       }
  280.    }
  281.    totalhits = otherhits = 0;
  282. }
  283.